﻿#region zh-CHS 2006 - 2010 DemoSoft 团队 | en 2006-2010 DemoSoft Team

//     NOTES
// ---------------
//
// This file is a part of the MMOSE(Massively Multiplayer Online Server Engine) for .NET.
//
//                              2006-2010 DemoSoft Team
//
//
// First Version : by H.Q.Cai - mailto:caihuanqing@hotmail.com

/***************************************************************************
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published
 *   by the Free Software Foundation; either version 2.1 of the License, or
 *   (at your option) any later version.
 *
 ***************************************************************************/

#region zh-CHS 包含名字空间 | en Include namespace
using System;
using System.Diagnostics;
using System.Threading;
using Demo.Mmose.Core.Common;
using Demo.Mmose.Core.Common.SafeCollections;
using Demo.Mmose.Core.Util;
using Demo.Mmose.Core.Entity.Creature;
using System.Collections.Generic;
#endregion

namespace Demo.Mmose.Core.Entity.Suit.Mail
{
    /// <summary>
    /// 
    /// </summary>
    public class MailBox<MailMessageT> where MailMessageT : MailMessage
    {
        #region zh-CHS 私有常量 | en Private Constants
        /// <summary>
        /// 
        /// </summary>
        private readonly static int DICTIONARY_CAPACITY_SIZE = 64;
        #endregion

        #region zh-CHS 构造和初始化和清理 | en Constructors and Initializers and Dispose
        /// <summary>
        /// 
        /// </summary>
        public MailBox()
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="Id"></param>
        public MailBox( Serial serial ) // serialization ctor
        {
            m_Serial = serial;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="Id"></param>
        public MailBox( CreatureBase owner )
        {
            m_Owner = owner;
        }
        #endregion

        #region zh-CHS 共有属性 | en Public Properties

        #region zh-CHS Serial属性 | en Public Properties

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private Serial m_Serial = new Serial();
        #endregion
        /// <summary>
        /// 道具的唯一序列号GUID
        /// </summary>
        public Serial Serial
        {
            get { return m_Serial; }
            set { m_Serial = value; }
        }

        #endregion

        #region zh-CHS Owner属性 | en Public Properties
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private CreatureBase m_Owner = null;
        #endregion
        /// <summary>
        /// 拥有者的对象
        /// </summary>
        public CreatureBase Owner
        {
            get { return m_Owner; }
            set { m_Owner = value; }
        }
        #endregion

        #region zh-CHS Count 属性 | en Public Properties
        /// <summary>
        /// 
        /// </summary>
        public int Count
        {
            get { return m_HighestMailMessages.Count + m_NormalMailMessages.Count + m_LowestMailMessages.Count; }
        }
        #endregion

        #region zh-CHS MailMessage列表 属性 | en Public Properties

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 低优先级邮件
        /// </summary>
        private SafeDictionary<long, MailMessageT> m_LowestMailMessages = new SafeDictionary<long, MailMessageT>( DICTIONARY_CAPACITY_SIZE );
        /// <summary>
        /// 通常优先级邮件
        /// </summary>
        private SafeDictionary<long, MailMessageT> m_NormalMailMessages = new SafeDictionary<long, MailMessageT>( DICTIONARY_CAPACITY_SIZE );
        /// <summary>
        /// 高优先级邮件
        /// </summary>
        private SafeDictionary<long, MailMessageT> m_HighestMailMessages = new SafeDictionary<long, MailMessageT>( DICTIONARY_CAPACITY_SIZE );
        #endregion
        /// <summary>
        /// 获取所有的邮件,没有排序
        /// </summary>
        [MultiThreadedWarning( "zh-CHS", "(邮件信息)当前的数组是列表临时产生的,不能保存数组用于以后操作:警告!" )]
        public MailMessageT[] ToArray()
        {
            int iCount = m_HighestMailMessages.Count + m_NormalMailMessages.Count + m_LowestMailMessages.Count;
            List<MailMessageT> mailMessageList = new List<MailMessageT>( iCount );

            MailMessageT[] mailMessageArray = m_HighestMailMessages.ToArrayValues();
            mailMessageList.AddRange( mailMessageArray );

            mailMessageArray = m_NormalMailMessages.ToArrayValues();
            mailMessageList.AddRange( mailMessageArray );

            mailMessageArray = m_LowestMailMessages.ToArrayValues();
            mailMessageList.AddRange( mailMessageArray );

            return mailMessageList.ToArray();
        }

        /// <summary>
        /// 获取优先级的邮件,没有排序
        /// </summary>
        [MultiThreadedWarning( "zh-CHS", "(邮件信息)当前的数组是列表临时产生的,不能保存数组用于以后操作:警告!" )]
        public MailMessageT[] ToArray( MailPriority mailPriority )
        {
            switch ( mailPriority )
            {
                case MailPriority.Highest:

                    return m_HighestMailMessages.ToArrayValues();

                case MailPriority.Normal:

                    return m_NormalMailMessages.ToArrayValues();

                case MailPriority.Lowest:

                    return m_LowestMailMessages.ToArrayValues();

                default:
                    // 缺省 通常优先级的 邮件
                    return m_NormalMailMessages.ToArrayValues();
            }
        }

        /// <summary>
        /// 根据优先级排序，后根据时间排序
        /// </summary>
        [MultiThreadedWarning( "zh-CHS", "(邮件信息)当前的数组是列表临时产生的,不能保存数组用于以后操作:警告!" )]
        public MailMessageT[] ToArrayAndSort( MailPrioritySortMode prioritySortMode, DeliveryTimeSortMode deliveryTimeSortMode )
        {
            int iCount = m_HighestMailMessages.Count + m_NormalMailMessages.Count + m_LowestMailMessages.Count;
            List<MailMessageT> mailMessageList = new List<MailMessageT>( iCount );

            MailMessageT[] mailMessageArray = null;
            if ( prioritySortMode == MailPrioritySortMode.Asc )
            {
                if ( m_LowestMailMessages.Count > 0 )
                {
                    mailMessageArray = m_LowestMailMessages.ToArrayValues();

                    if ( deliveryTimeSortMode == DeliveryTimeSortMode.Asc )
                        Array.Sort<MailMessageT>( mailMessageArray, ( x, y ) => ( x.DeliveryTime.ToFileTimeUtc() ).CompareTo( y.DeliveryTime.ToFileTimeUtc() ) );
                    else
                        Array.Sort<MailMessageT>( mailMessageArray, ( x, y ) => ( y.DeliveryTime.ToFileTimeUtc() ).CompareTo( x.DeliveryTime.ToFileTimeUtc() ) );

                    mailMessageList.AddRange( mailMessageArray );
                }

                if ( m_NormalMailMessages.Count > 0 )
                {
                    mailMessageArray = m_NormalMailMessages.ToArrayValues();

                    if ( deliveryTimeSortMode == DeliveryTimeSortMode.Asc )
                        Array.Sort<MailMessageT>( mailMessageArray, ( x, y ) => ( x.DeliveryTime.ToFileTimeUtc() ).CompareTo( y.DeliveryTime.ToFileTimeUtc() ) );
                    else
                        Array.Sort<MailMessageT>( mailMessageArray, ( x, y ) => ( y.DeliveryTime.ToFileTimeUtc() ).CompareTo( x.DeliveryTime.ToFileTimeUtc() ) );

                    mailMessageList.AddRange( mailMessageArray );
                }

                if ( m_HighestMailMessages.Count > 0 )
                {
                    mailMessageArray = m_HighestMailMessages.ToArrayValues();

                    if ( deliveryTimeSortMode == DeliveryTimeSortMode.Asc )
                        Array.Sort<MailMessageT>( mailMessageArray, ( x, y ) => ( x.DeliveryTime.ToFileTimeUtc() ).CompareTo( y.DeliveryTime.ToFileTimeUtc() ) );
                    else
                        Array.Sort<MailMessageT>( mailMessageArray, ( x, y ) => ( y.DeliveryTime.ToFileTimeUtc() ).CompareTo( x.DeliveryTime.ToFileTimeUtc() ) );

                    mailMessageList.AddRange( mailMessageArray );
                }
            }
            else
            {
                if ( m_HighestMailMessages.Count > 0 )
                {
                    mailMessageArray = m_HighestMailMessages.ToArrayValues();

                    if ( deliveryTimeSortMode == DeliveryTimeSortMode.Asc )
                        Array.Sort<MailMessageT>( mailMessageArray, ( x, y ) => ( x.DeliveryTime.ToFileTimeUtc() ).CompareTo( y.DeliveryTime.ToFileTimeUtc() ) );
                    else
                        Array.Sort<MailMessageT>( mailMessageArray, ( x, y ) => ( y.DeliveryTime.ToFileTimeUtc() ).CompareTo( x.DeliveryTime.ToFileTimeUtc() ) );

                    mailMessageList.AddRange( mailMessageArray );
                }

                if ( m_NormalMailMessages.Count > 0 )
                {
                    mailMessageArray = m_NormalMailMessages.ToArrayValues();

                    if ( deliveryTimeSortMode == DeliveryTimeSortMode.Asc )
                        Array.Sort<MailMessageT>( mailMessageArray, ( x, y ) => ( x.DeliveryTime.ToFileTimeUtc() ).CompareTo( y.DeliveryTime.ToFileTimeUtc() ) );
                    else
                        Array.Sort<MailMessageT>( mailMessageArray, ( x, y ) => ( y.DeliveryTime.ToFileTimeUtc() ).CompareTo( x.DeliveryTime.ToFileTimeUtc() ) );

                    mailMessageList.AddRange( mailMessageArray );
                }

                if ( m_LowestMailMessages.Count > 0 )
                {
                    mailMessageArray = m_LowestMailMessages.ToArrayValues();

                    if ( deliveryTimeSortMode == DeliveryTimeSortMode.Asc )
                        Array.Sort<MailMessageT>( mailMessageArray, ( x, y ) => ( x.DeliveryTime.ToFileTimeUtc() ).CompareTo( y.DeliveryTime.ToFileTimeUtc() ) );
                    else
                        Array.Sort<MailMessageT>( mailMessageArray, ( x, y ) => ( y.DeliveryTime.ToFileTimeUtc() ).CompareTo( x.DeliveryTime.ToFileTimeUtc() ) );

                    mailMessageList.AddRange( mailMessageArray );
                }
            }

            return mailMessageList.ToArray();
        }

        /// <summary>
        /// 根据时间排序
        /// </summary>
        /// <param name="deliveryTimeSortMode"></param>
        /// <returns></returns>
        [MultiThreadedWarning( "zh-CHS", "(邮件信息)当前的数组是列表临时产生的,不能保存数组用于以后操作:警告!" )]
        public MailMessageT[] ToArrayAndSort( DeliveryTimeSortMode deliveryTimeSortMode )
        {
            int iCount = m_HighestMailMessages.Count + m_NormalMailMessages.Count + m_LowestMailMessages.Count;
            List<MailMessageT> mailMessageList = new List<MailMessageT>( iCount );

            MailMessageT[] mailMessageArray = m_LowestMailMessages.ToArrayValues();
            mailMessageList.AddRange( mailMessageArray );

            mailMessageArray = m_NormalMailMessages.ToArrayValues();
            mailMessageList.AddRange( mailMessageArray );

            mailMessageArray = m_HighestMailMessages.ToArrayValues();
            mailMessageList.AddRange( mailMessageArray );

            mailMessageArray = mailMessageList.ToArray();

            if ( deliveryTimeSortMode == DeliveryTimeSortMode.Asc )
                Array.Sort<MailMessageT>( mailMessageArray, ( x, y ) => ( x.DeliveryTime.ToFileTimeUtc() ).CompareTo( y.DeliveryTime.ToFileTimeUtc() ) );
            else
                Array.Sort<MailMessageT>( mailMessageArray, ( x, y ) => ( y.DeliveryTime.ToFileTimeUtc() ).CompareTo( x.DeliveryTime.ToFileTimeUtc() ) );

            return mailMessageArray;
        }

        #region zh-CHS 共有方法 | en Public Methods

        /// <summary>
        /// 添加邮件
        /// </summary>
        /// <param name="item"></param>
        public bool AddMailMessage( long lMailMessageId, MailMessageT mailMessageT )
        {
            if ( mailMessageT == null )
                throw new ArgumentNullException( "mailMessageT", "MailBox<MailMessageT>.AddMailMessage(...) - mailMessageT == null error!" );

            EventHandler<AddingMailMessageCallEventArgs<MailMessageT>> tempBeforeEventArgs = m_EventAddingMailMessage;
            if ( tempBeforeEventArgs != null )
            {
                AddingMailMessageCallEventArgs<MailMessageT> eventArgs = new AddingMailMessageCallEventArgs<MailMessageT>( mailMessageT, this );
                tempBeforeEventArgs( this, eventArgs );

                if ( eventArgs.IsCancel == true )
                    return false;
            }

            switch ( mailMessageT.MailPriority )
            {
                case MailPriority.Highest:

                    m_HighestMailMessages.Add( lMailMessageId, mailMessageT );
                    break;
                case MailPriority.Normal:

                    m_NormalMailMessages.Add( lMailMessageId, mailMessageT );
                    break;
                case MailPriority.Lowest:

                    m_LowestMailMessages.Add( lMailMessageId, mailMessageT );
                    break;
                default:

                    m_LowestMailMessages.Add( lMailMessageId, mailMessageT );
                    break;
            }


            EventHandler<AddedMailMessageCallEventArgs<MailMessageT>> tempAfterEventArgs = m_EventAddedMailMessage;
            if ( tempAfterEventArgs != null )
            {
                AddedMailMessageCallEventArgs<MailMessageT> eventArgs = new AddedMailMessageCallEventArgs<MailMessageT>( mailMessageT, this );
                tempAfterEventArgs( this, eventArgs );
            }

            return true;
        }

        /// <summary>
        /// 移出邮件
        /// </summary>
        /// <param name="item"></param>
        public bool RemoveMailMessage( long lMailMessageId )
        {
            MailMessageT mailMessageT = FindMailMessageOnId( lMailMessageId );
            if ( mailMessageT == null )
                return false;

            EventHandler<RemovingMailMessageCallEventArgs<MailMessageT>> tempBeforeEventArgs = m_EventRemovingMailMessage;
            if ( tempBeforeEventArgs != null )
            {
                RemovingMailMessageCallEventArgs<MailMessageT> eventArgs = new RemovingMailMessageCallEventArgs<MailMessageT>( mailMessageT, this );
                tempBeforeEventArgs( this, eventArgs );

                if ( eventArgs.IsCancel == true )
                    return false;
            }

            switch ( mailMessageT.MailPriority )
            {
                case MailPriority.Highest:

                    m_HighestMailMessages.Remove( lMailMessageId );
                    break;
                case MailPriority.Normal:

                    m_NormalMailMessages.Remove( lMailMessageId );
                    break;
                case MailPriority.Lowest:

                    m_LowestMailMessages.Remove( lMailMessageId );
                    break;
                default:

                    m_LowestMailMessages.Remove( lMailMessageId );
                    break;
            }

            EventHandler<RemovedMailMessageCallEventArgs<MailMessageT>> tempAfterEventArgs = m_EventRemovedMailMessage;
            if ( tempAfterEventArgs != null )
            {
                RemovedMailMessageCallEventArgs<MailMessageT> eventArgs = new RemovedMailMessageCallEventArgs<MailMessageT>( mailMessageT, this );
                tempAfterEventArgs( this, eventArgs );
            }

            return true;
        }

        /// <summary>
        /// 在信箱找邮件
        /// </summary>
        /// <param name="layer"></param>
        /// <returns></returns>
        public MailMessageT FindMailMessageOnId( long lMailMessageId )
        {
            MailMessageT mailMessage = default( MailMessageT );

            if ( m_NormalMailMessages.TryGetValue( lMailMessageId, out mailMessage ) == true )
                return mailMessage;

            if ( m_HighestMailMessages.TryGetValue( lMailMessageId, out mailMessage ) == true )
                return mailMessage;

            if ( m_LowestMailMessages.TryGetValue( lMailMessageId, out mailMessage ) == true )
                return mailMessage;

            return mailMessage;
        }

        #endregion

        #endregion

        #endregion

        #region zh-CHS 共有事件 | en Public Event

        #region zh-CHS AddMailMessageCall事件 | en Public Event
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private EventHandler<AddingMailMessageCallEventArgs<MailMessageT>> m_EventAddingMailMessage;
        /// <summary>
        /// 
        /// </summary>
        private SpinLock m_LockEventAddingMailMessage = new SpinLock();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public event EventHandler<AddingMailMessageCallEventArgs<MailMessageT>> AddingMailMessage
        {
            add
            {
                SpinLockEx.ReliableEnter( ref m_LockEventAddingMailMessage );
                try
                {
                    m_EventAddingMailMessage += value;
                }
                finally
                {
                    m_LockEventAddingMailMessage.Exit();
                }
            }
            remove
            {
                SpinLockEx.ReliableEnter( ref m_LockEventAddingMailMessage );
                try
                {
                    m_EventAddingMailMessage -= value;
                }
                finally
                {
                    m_LockEventAddingMailMessage.Exit();
                }
            }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private EventHandler<AddedMailMessageCallEventArgs<MailMessageT>> m_EventAddedMailMessage;
        /// <summary>
        /// 
        /// </summary>
        private SpinLock m_LockEventAddedMailMessage = new SpinLock();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public event EventHandler<AddedMailMessageCallEventArgs<MailMessageT>> AddedMailMessage
        {
            add
            {
                SpinLockEx.ReliableEnter( ref m_LockEventAddedMailMessage );
                try
                {
                    m_EventAddedMailMessage += value;
                }
                finally
                {
                    m_LockEventAddedMailMessage.Exit();
                }
            }
            remove
            {
                SpinLockEx.ReliableEnter( ref m_LockEventAddedMailMessage );
                try
                {
                    m_EventAddedMailMessage -= value;
                }
                finally
                {
                    m_LockEventAddedMailMessage.Exit();
                }
            }
        }
        #endregion

        #region zh-CHS RemoveMailMessageCall事件 | en Public Event
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private EventHandler<RemovingMailMessageCallEventArgs<MailMessageT>> m_EventRemovingMailMessage;
        /// <summary>
        /// 
        /// </summary>
        private SpinLock m_LockEventRemovingMailMessage = new SpinLock();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public event EventHandler<RemovingMailMessageCallEventArgs<MailMessageT>> RemovingMailMessage
        {
            add
            {
                SpinLockEx.ReliableEnter( ref m_LockEventRemovingMailMessage );
                try
                {
                    m_EventRemovingMailMessage += value;
                }
                finally
                {
                    m_LockEventRemovingMailMessage.Exit();
                }
            }
            remove
            {
                SpinLockEx.ReliableEnter( ref m_LockEventRemovingMailMessage );
                try
                {
                    m_EventRemovingMailMessage -= value;
                }
                finally
                {
                    m_LockEventRemovingMailMessage.Exit();
                }
            }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private EventHandler<RemovedMailMessageCallEventArgs<MailMessageT>> m_EventRemovedMailMessage;
        /// <summary>
        /// 
        /// </summary>
        private SpinLock m_LockEventRemovedMailMessage = new SpinLock();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public event EventHandler<RemovedMailMessageCallEventArgs<MailMessageT>> RemovedMailMessage
        {
            add
            {
                SpinLockEx.ReliableEnter( ref m_LockEventRemovedMailMessage );
                try
                {
                    m_EventRemovedMailMessage += value;
                }
                finally
                {
                    m_LockEventRemovedMailMessage.Exit();
                }
            }
            remove
            {
                SpinLockEx.ReliableEnter( ref m_LockEventRemovedMailMessage );
                try
                {
                    m_EventRemovedMailMessage -= value;
                }
                finally
                {
                    m_LockEventRemovedMailMessage.Exit();
                }
            }
        }
        #endregion

        #endregion
    }
}
#endregion